package com.volunteer.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.volunteer.entity.Activity;
import com.volunteer.entity.ActivityEnrollment;
import com.volunteer.entity.PointRecord;
import com.volunteer.entity.VolunteerProfile;
import com.volunteer.mapper.ActivityEnrollmentMapper;
import com.volunteer.mapper.ActivityMapper;
import com.volunteer.mapper.PointRecordMapper;
import com.volunteer.mapper.VolunteerProfileMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 活动服务
 */
@Service
@RequiredArgsConstructor
public class ActivityService {

    private final ActivityMapper activityMapper;
    private final ActivityEnrollmentMapper enrollmentMapper;
    private final PointRecordMapper pointRecordMapper;
    private final VolunteerProfileMapper volunteerProfileMapper;

    /**
     * 分页查询活动列表
     */
    public IPage<Activity> getActivityList(int page, int size, String status, String category) {
        Page<Activity> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper<>();
        
        if (status != null && !status.isEmpty()) {
            queryWrapper.eq(Activity::getStatus, status);
        }
        if (category != null && !category.isEmpty()) {
            queryWrapper.eq(Activity::getCategory, category);
        }
        
        queryWrapper.orderByDesc(Activity::getCreateTime);
        return activityMapper.selectPage(pageParam, queryWrapper);
    }

    /**
     * 获取活动详情
     */
    public Activity getActivityById(Long id) {
        return activityMapper.selectById(id);
    }

    /**
     * 创建活动
     */
    public Activity createActivity(Activity activity) {
        activity.setCurrentParticipants(0);
        if (activity.getStatus() == null) {
            activity.setStatus("DRAFT");
        }
        activityMapper.insert(activity);
        return activity;
    }

    /**
     * 更新活动
     */
    public void updateActivity(Activity activity) {
        activityMapper.updateById(activity);
    }

    /**
     * 删除活动
     */
    public void deleteActivity(Long id) {
        activityMapper.deleteById(id);
    }

    /**
     * 报名活动
     */
    @Transactional
    public void enrollActivity(Long activityId, Long userId, String applyReason) {
        // 检查是否被限制报名
        checkEnrollmentRestriction(userId);

        // 检查是否已报名
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getActivityId, activityId)
                .eq(ActivityEnrollment::getUserId, userId);
        if (enrollmentMapper.selectCount(queryWrapper) > 0) {
            throw new RuntimeException("您已报名该活动");
        }

        // 检查活动是否可报名
        Activity activity = activityMapper.selectById(activityId);
        if (!"RECRUITING".equals(activity.getStatus())) {
            throw new RuntimeException("该活动当前不可报名");
        }

        // 检查人数限制
        if (activity.getMaxParticipants() > 0 &&
                activity.getCurrentParticipants() >= activity.getMaxParticipants()) {
            throw new RuntimeException("活动人数已满");
        }

        // 创建报名记录
        ActivityEnrollment enrollment = new ActivityEnrollment();
        enrollment.setActivityId(activityId);
        enrollment.setUserId(userId);
        enrollment.setStatus("ENROLLED");
        enrollment.setApplyReason(applyReason);
        enrollmentMapper.insert(enrollment);

        // 更新活动参与人数
        activity.setCurrentParticipants(activity.getCurrentParticipants() + 1);
        activityMapper.updateById(activity);
    }

    /**
     * 取消报名（带积分扣除逻辑）
     */
    @Transactional
    public void cancelEnrollment(Long activityId, Long userId, String cancelReason) {
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getActivityId, activityId)
                .eq(ActivityEnrollment::getUserId, userId);
        ActivityEnrollment enrollment = enrollmentMapper.selectOne(queryWrapper);
        
        if (enrollment == null) {
            throw new RuntimeException("未找到报名记录");
        }

        if ("CANCELLED".equals(enrollment.getStatus())) {
            throw new RuntimeException("已经取消过了");
        }

        Activity activity = activityMapper.selectById(activityId);
        java.time.LocalDateTime now = java.time.LocalDateTime.now();
        int penaltyPoints = 0;
        String penaltyReason = "";

        // 计算扣除积分
        if (activity.getStartTime().isAfter(now)) {
            // 活动开始前取消 - 少量扣分（5分）
            penaltyPoints = 5;
            penaltyReason = "活动开始前取消报名";
        } else {
            // 活动开始后取消 - 较多扣分（15分）
            penaltyPoints = 15;
            penaltyReason = "活动开始后取消报名";
        }

        // 检查是否恶意取消
        LambdaQueryWrapper<VolunteerProfile> profileQuery = new LambdaQueryWrapper<>();
        profileQuery.eq(VolunteerProfile::getUserId, userId);
        VolunteerProfile profile = volunteerProfileMapper.selectOne(profileQuery);
        
        if (profile != null) {
            // 检查30天内取消次数
            if (profile.getLastCancelTime() != null) {
                long daysSinceLastCancel = java.time.Duration.between(
                    profile.getLastCancelTime(), now).toDays();
                
                if (daysSinceLastCancel <= 30) {
                    int currentCancelCount = profile.getCancelCount() != null ? profile.getCancelCount() : 0;
                    profile.setCancelCount(currentCancelCount + 1);
                    
                    // 恶意多次取消（30天内3次以上）
                    if (profile.getCancelCount() >= 3) {
                        penaltyPoints = penaltyPoints * 2;  // 加倍扣分
                        profile.setIsBlacklisted(1);
                        profile.setBlacklistReason("30天内多次取消活动报名");
                        profile.setBlacklistUntil(now.plusDays(30));  // 限制30天
                        penaltyReason = penaltyReason + "（恶意多次取消，加倍扣分并限制报名30天）";
                    }
                } else {
                    // 超过30天，重置计数
                    profile.setCancelCount(1);
                }
            } else {
                profile.setCancelCount(1);
            }
            
            profile.setLastCancelTime(now);
            
            // 扣除积分
            if (penaltyPoints > 0) {
                int newTotalPoints = Math.max(0, profile.getTotalPoints() - penaltyPoints);
                profile.setTotalPoints(newTotalPoints);
                
                // 记录积分扣除
                PointRecord pointRecord = new PointRecord();
                pointRecord.setUserId(userId);
                pointRecord.setPoints(-penaltyPoints);
                pointRecord.setType("PENALTY");
                pointRecord.setSourceId(activityId);
                pointRecord.setDescription(penaltyReason + "：" + activity.getTitle());
                pointRecordMapper.insert(pointRecord);
            }
            
            volunteerProfileMapper.updateById(profile);
        }

        // 更新报名状态
        enrollment.setStatus("CANCELLED");
        enrollment.setCancelTime(now);
        enrollment.setCancelReason(cancelReason);
        enrollment.setPenaltyPoints(penaltyPoints);
        enrollmentMapper.updateById(enrollment);

        // 更新活动参与人数
        if (activity.getCurrentParticipants() > 0) {
            activity.setCurrentParticipants(activity.getCurrentParticipants() - 1);
            activityMapper.updateById(activity);
        }
    }

    /**
     * 完成活动并结算积分
     */
    @Transactional
    public void completeActivity(Long activityId) {
        Activity activity = activityMapper.selectById(activityId);
        activity.setStatus("COMPLETED");
        activityMapper.updateById(activity);

        // 获取所有已通过的报名记录
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getActivityId, activityId)
                .in(ActivityEnrollment::getStatus, "APPROVED", "ENROLLED");
        List<ActivityEnrollment> enrollments = enrollmentMapper.selectList(queryWrapper);

        java.time.LocalDateTime now = java.time.LocalDateTime.now();

        // 计算活动设置的时长（活动结束时间 - 开始时间）
        long activityHours = 0;
        if (activity.getStartTime() != null && activity.getEndTime() != null) {
            activityHours = java.time.Duration.between(
                activity.getStartTime(), activity.getEndTime()).toHours();
        }

        // 发放积分和计算服务时长
        for (ActivityEnrollment enrollment : enrollments) {
            // 如果已签到但未签退，自动签退
            if (enrollment.getCheckInTime() != null && enrollment.getCheckOutTime() == null) {
                enrollment.setCheckOutTime(now);
            }

            // 更新报名状态
            enrollment.setStatus("COMPLETED");
            enrollmentMapper.updateById(enrollment);

            // 如果已签到（无论是否签退），累计活动设置的服务时长
            if (enrollment.getCheckInTime() != null && activityHours > 0) {
                LambdaQueryWrapper<VolunteerProfile> profileQuery = new LambdaQueryWrapper<>();
                profileQuery.eq(VolunteerProfile::getUserId, enrollment.getUserId());
                VolunteerProfile profile = volunteerProfileMapper.selectOne(profileQuery);
                
                if (profile != null) {
                    java.math.BigDecimal currentHours = profile.getTotalHours() != null ? 
                        profile.getTotalHours() : java.math.BigDecimal.ZERO;
                    profile.setTotalHours(currentHours.add(java.math.BigDecimal.valueOf(activityHours)));
                    volunteerProfileMapper.updateById(profile);
                }
            }

            // 添加积分记录
            PointRecord pointRecord = new PointRecord();
            pointRecord.setUserId(enrollment.getUserId());
            pointRecord.setPoints(activity.getPointsReward());
            pointRecord.setType("ACTIVITY");
            pointRecord.setSourceId(activityId);
            pointRecord.setDescription("完成活动：" + activity.getTitle());
            pointRecordMapper.insert(pointRecord);

            // 更新志愿者总积分
            LambdaQueryWrapper<VolunteerProfile> profileQuery2 = new LambdaQueryWrapper<>();
            profileQuery2.eq(VolunteerProfile::getUserId, enrollment.getUserId());
            VolunteerProfile profile2 = volunteerProfileMapper.selectOne(profileQuery2);
            if (profile2 != null) {
                int currentPoints = profile2.getTotalPoints() != null ? profile2.getTotalPoints() : 0;
                profile2.setTotalPoints(currentPoints + activity.getPointsReward());
                volunteerProfileMapper.updateById(profile2);
            }
        }
    }

    /**
     * 获取用户的报名记录
     */
    public List<ActivityEnrollment> getUserEnrollments(Long userId) {
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getUserId, userId)
                .orderByDesc(ActivityEnrollment::getCreateTime);
        return enrollmentMapper.selectList(queryWrapper);
    }

    /**
     * 获取活动的报名列表
     */
    public List<ActivityEnrollment> getActivityEnrollments(Long activityId) {
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getActivityId, activityId)
                .orderByDesc(ActivityEnrollment::getCreateTime);
        return enrollmentMapper.selectList(queryWrapper);
    }

    /**
     * 审核报名
     */
    public void approveEnrollment(Long enrollmentId, String status) {
        ActivityEnrollment enrollment = enrollmentMapper.selectById(enrollmentId);
        enrollment.setStatus(status);
        enrollmentMapper.updateById(enrollment);
    }

    /**
     * 签到
     */
    @Transactional
    public void checkIn(Long activityId, Long userId) {
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getActivityId, activityId)
                .eq(ActivityEnrollment::getUserId, userId);
        ActivityEnrollment enrollment = enrollmentMapper.selectOne(queryWrapper);
        
        if (enrollment == null) {
            throw new RuntimeException("未找到报名记录");
        }

        if (!"APPROVED".equals(enrollment.getStatus()) && !"ENROLLED".equals(enrollment.getStatus())) {
            throw new RuntimeException("报名状态异常，无法签到");
        }

        if (enrollment.getCheckInTime() != null) {
            throw new RuntimeException("已经签到过了");
        }

        // 检查是否被限制
        LambdaQueryWrapper<VolunteerProfile> profileQuery = new LambdaQueryWrapper<>();
        profileQuery.eq(VolunteerProfile::getUserId, userId);
        VolunteerProfile profile = volunteerProfileMapper.selectOne(profileQuery);
        
        if (profile != null && profile.getIsBlacklisted() != null && profile.getIsBlacklisted() == 1) {
            if (profile.getBlacklistUntil() != null && 
                profile.getBlacklistUntil().isAfter(java.time.LocalDateTime.now())) {
                throw new RuntimeException("您已被限制报名活动，限制到期时间：" + profile.getBlacklistUntil());
            } else {
                // 过期自动解除
                profile.setIsBlacklisted(0);
                profile.setBlacklistReason(null);
                profile.setBlacklistUntil(null);
                volunteerProfileMapper.updateById(profile);
            }
        }

        enrollment.setCheckInTime(java.time.LocalDateTime.now());
        enrollmentMapper.updateById(enrollment);
    }

    /**
     * 签退
     */
    @Transactional
    public void checkOut(Long activityId, Long userId) {
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getActivityId, activityId)
                .eq(ActivityEnrollment::getUserId, userId);
        ActivityEnrollment enrollment = enrollmentMapper.selectOne(queryWrapper);
        
        if (enrollment == null) {
            throw new RuntimeException("未找到报名记录");
        }

        if (enrollment.getCheckInTime() == null) {
            throw new RuntimeException("尚未签到，无法签退");
        }

        if (enrollment.getCheckOutTime() != null) {
            throw new RuntimeException("已经签退过了");
        }

        enrollment.setCheckOutTime(java.time.LocalDateTime.now());
        enrollment.setStatus("COMPLETED");
        enrollmentMapper.updateById(enrollment);

        // 使用活动设置的时长（结束时间 - 开始时间）
        Activity activity = activityMapper.selectById(activityId);
        if (activity.getStartTime() != null && activity.getEndTime() != null) {
            long hours = java.time.Duration.between(
                activity.getStartTime(), activity.getEndTime()).toHours();
            
            LambdaQueryWrapper<VolunteerProfile> profileQuery = new LambdaQueryWrapper<>();
            profileQuery.eq(VolunteerProfile::getUserId, userId);
            VolunteerProfile profile = volunteerProfileMapper.selectOne(profileQuery);
            
            if (profile != null) {
                java.math.BigDecimal currentHours = profile.getTotalHours() != null ? 
                    profile.getTotalHours() : java.math.BigDecimal.ZERO;
                profile.setTotalHours(currentHours.add(java.math.BigDecimal.valueOf(hours)));
                volunteerProfileMapper.updateById(profile);
            }
        }
    }

    /**
     * 检查未签退的记录并扣分
     * 应由定时任务在活动结束后调用
     */
    @Transactional
    public void checkMissingCheckOut(Long activityId) {
        Activity activity = activityMapper.selectById(activityId);
        
        // 只有活动结束后才检查
        if (!"COMPLETED".equals(activity.getStatus())) {
            return;
        }

        // 查找签到但未签退的记录
        LambdaQueryWrapper<ActivityEnrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActivityEnrollment::getActivityId, activityId)
                .isNotNull(ActivityEnrollment::getCheckInTime)
                .isNull(ActivityEnrollment::getCheckOutTime);
        List<ActivityEnrollment> missingCheckOuts = enrollmentMapper.selectList(queryWrapper);

        for (ActivityEnrollment enrollment : missingCheckOuts) {
            // 扣除积分（20分）
            int penaltyPoints = 20;
            
            LambdaQueryWrapper<VolunteerProfile> profileQuery = new LambdaQueryWrapper<>();
            profileQuery.eq(VolunteerProfile::getUserId, enrollment.getUserId());
            VolunteerProfile profile = volunteerProfileMapper.selectOne(profileQuery);
            
            if (profile != null) {
                // 扣除积分
                int newTotalPoints = Math.max(0, profile.getTotalPoints() - penaltyPoints);
                profile.setTotalPoints(newTotalPoints);
                
                // 标记失信
                profile.setIsBlacklisted(1);
                profile.setBlacklistReason("签到后未签退");
                profile.setBlacklistUntil(java.time.LocalDateTime.now().plusDays(15));  // 限制15天
                
                volunteerProfileMapper.updateById(profile);
                
                // 记录积分扣除
                PointRecord pointRecord = new PointRecord();
                pointRecord.setUserId(enrollment.getUserId());
                pointRecord.setPoints(-penaltyPoints);
                pointRecord.setType("PENALTY");
                pointRecord.setSourceId(activityId);
                pointRecord.setDescription("签到后未签退，标记失信并限制报名15天：" + activity.getTitle());
                pointRecordMapper.insert(pointRecord);
            }
            
            // 更新报名状态
            enrollment.setStatus("INCOMPLETE");
            enrollment.setPenaltyPoints(penaltyPoints);
            enrollmentMapper.updateById(enrollment);
        }
    }

    /**
     * 报名前检查是否被限制
     */
    public void checkEnrollmentRestriction(Long userId) {
        LambdaQueryWrapper<VolunteerProfile> profileQuery = new LambdaQueryWrapper<>();
        profileQuery.eq(VolunteerProfile::getUserId, userId);
        VolunteerProfile profile = volunteerProfileMapper.selectOne(profileQuery);
        
        if (profile != null && profile.getIsBlacklisted() != null && profile.getIsBlacklisted() == 1) {
            if (profile.getBlacklistUntil() != null && 
                profile.getBlacklistUntil().isAfter(java.time.LocalDateTime.now())) {
                throw new RuntimeException("您已被限制报名活动至 " + profile.getBlacklistUntil() + 
                    "，原因：" + profile.getBlacklistReason());
            } else {
                // 过期自动解除
                profile.setIsBlacklisted(0);
                profile.setBlacklistReason(null);
                profile.setBlacklistUntil(null);
                volunteerProfileMapper.updateById(profile);
            }
        }
    }
}

